/**
 * Created with IntelliJ IDEA.
 * User: liulinhui
 * Date: 18-10-22
 * Time: 下午4:50
 * Description: datxService
 */
import {getStorage, putStorage} from '../utils/storage'
import ecc from 'eosjs-ecc'
import crypto from '../utils/crypto.js'
import _ from 'lodash'


import DATx from './datxjs/src/index.js';

const chainId = "1c6ae7719a2a3b4ecb19584a30ff510ba1b6ded86e1fd8b8fc22f1179c622a32";
const httpEndpoint = "http://172.31.7.68:8888"
const datx = DATx({httpEndpoint, chainId, keyProvider: () => userProvidedKey});

let userProvidedKey = null;

/**
 * 获取所有账户
 * @returns {any}
 */
export function getAllMyAccount() {
  let account = getStorage('datx:account');
  return JSON.parse(account);
}

/**
 * 根据账户名获取datx账户
 * @param name 用户名
 */
export function getAccountByName(name) {
  let storage = getStorage('datx:account');
  if (!storage) return null;
  storage = JSON.parse(storage);
  let account = null;
  _(storage).forEach(obj => {
      if (name === obj.name)
        account = obj;
    }
  );
  return account;
}

/**
 * 根据私钥生成公钥
 * @param wif 私钥
 */
export function getPubKeyByWif(wif) {
  let publicKey = ecc.privateToPublic(wif);
  publicKey = publicKey.replace('EOS', 'DATX');
  return publicKey;
}

/**
 * 导入账户
 * @param privateKey 私钥
 * @param secret 密码
 * @param name 用户名
 * @param status 状态
 * @returns {string}creating：创建中  ，created：已经创建
 */
export function importAccount(privateKey, secret, name, status) {
  try {
    let publicKey = ecc.privateToPublic(privateKey);
    publicKey = publicKey.replace('EOS', 'DATX');
    privateKey = crypto.encryptMessageWithSecret(privateKey, secret);
    let data = {
      date: Date(),
      publicKey: publicKey,
      privateKey: privateKey,
      name: name,
      status: status,  //creating:正在创建用户名 ， created：创建用户名完成
    };
    let storage = getStorage('datx:account');
    if (storage) {
      storage = JSON.parse(storage);
      let exits = false;
      _(storage).forEach(function (obj) {
        if (obj.name === name) {
          exits = true;
        }
      });
      if (exits) {
        return '该用户已经存在了';
      }
      storage.push(data);
    } else {
      storage = [];
      storage.push(data)
    }
    putStorage('datx:account', JSON.stringify(storage))
  } catch (error) {
    return '导入私钥出错';
  }
  return '';
}

/**
 *校验私钥合法性
 * @param pri
 */
export function isValidPrivate(pri) {
  return ecc.isValidPrivate(pri);
}

/**
 * 获取所有的外部账号
 * @returns {any}
 */
export function getAllOuterAccount() {
  let account = getStorage('outer:account');
  return JSON.parse(account);
}

/**
 *  * 导入外部账户
 * @param type 类型:ETH,BTC,EOS
 * @param privateKey 私钥
 * @param secret 密码
 * @param publicKey 公钥
 * @param address 地址
 */
export function addOuterAccount(type, privateKey, publicKey, address, secret) {
  privateKey = crypto.encryptMessageWithSecret(privateKey, secret);
  let data = {
    date: Date(),
    privateKey: privateKey,
    publicKey: publicKey,
    address: address,
    type: type
  };
  let storage = getStorage('outer:account');
  if (storage) {
    storage = JSON.parse(storage);
    let exits = false;
    _(storage).forEach(function (obj) {
      if (obj.type === type && obj.address === address) {
        exits = true;
      }
    });
    if (exits) {
      return '该账户已经存在了';
    }
    storage.push(data);
  } else {
    storage = [];
    storage.push(data)
  }
  putStorage('outer:account', JSON.stringify(storage))
  return '';
}

/**
 * 根据类型以及地址查询账户信息
 * @param type ETH,BTC
 * @param address 地址
 * @param secret 密码
 */
export function selectOuterAccountByAddress(type, address, secret) {
  if(type=="ETH"){
    let storage = getStorage('outer:account');
    if (!storage) return null;
    storage = JSON.parse(storage);
    let account = null;
    _(storage).forEach(obj => {
        if (type === obj.type && address === obj.address)
          account = obj;
      }
    );
    if (account) {
      let nonce = account.privateKey.nonce;
      let encryptedMessage = account.privateKey.encryptedMessage;
      account.privateKey = crypto.decryptMessageWithSecret(encryptedMessage, nonce, secret)
    }
    return account;
  }else {
    let storage = getStorage('datx:account');
    if (!storage) return null;
    storage = JSON.parse(storage);
    let account = null;
    _(storage).forEach(obj => {
        if (address === obj.name)
          account = obj;
      }
    );
    if (account) {
      let nonce = account.privateKey.nonce;
      let encryptedMessage = account.privateKey.encryptedMessage;
      account.privateKey = crypto.decryptMessageWithSecret(encryptedMessage, nonce, secret)
    }
    return account;
  }

}

/**
 * datx根据地址查询账户信息
 * @param name 地址
 * @param secret 密码
 */
export function selectOuterDatx(name, secret) {
  let storage = getStorage('datx:account');
  if (!storage) return null;
  storage = JSON.parse(storage);
  let account = null;
  _(storage).forEach(obj => {
      if (name === obj.name)
        account = obj;
    }
  );
  if (account) {
    let nonce = account.privateKey.nonce;
    let encryptedMessage = account.privateKey.encryptedMessage;
    account.privateKey = crypto.decryptMessageWithSecret(encryptedMessage, nonce, secret)
  }
  return account;
}

/**
 * 根据类型查询账户
 * @param type ETH ，EOS
 */
export function selectOuterAccountByType(type) {
  let storage = getStorage('outer:account');
  if (!storage) return null;
  storage = JSON.parse(storage);
  let account = [];
  _(storage).forEach(obj => {
      if (type === obj.type)
        account.push(obj);
    }
  );
  return account;
}



/**
 * 发送交易
 * @param from 发送者
 * @param to 接受者
 * @param amount 金额 '20.0000 DATX'
 * @param memo 附加信息
 * @param secret 私钥
 * @param cb  回调函数
 */
export function sendTrx(from,to,amount,memo,secret,cb) {
  userProvidedKey = secret;

  let options = {authorization: from + '@active'};
  datx.transfer(from, to, amount, memo,options,cb);
}


/**
 * 获取账户余额
 * @param type DETH,DBTC,DEOS
 * @param account 账户名
 * @param cb 回调函数
 */
export function getBalance(type,account,cb) {
  datx.getCurrencyBalance('datxos.dtoke', account, type, cb);
}

/**
 * 购买内存
 * @param buyer 购买者
 * @param receiver 接收者
 * @param quant 数量 "20.0000 DATX"
 * @param secret 私钥
 * @param cb 回调函数
 */
export function buyram(buyer,receiver,quant,secret,cb) {
  userProvidedKey = secret;
  let options = {authorization: buyer + '@active'};
  datx.buyram(buyer,receiver,quant,options,cb);
}


/**
 * 出售内存
 * @param account 账号
 * @param bytes 数量(传整数)
 * @param secret 私钥
 * @param cb 回调函数
 */
export function sellram(account,bytes,secret,cb) {
  userProvidedKey = secret;
  let options = {authorization: account + '@active'};
  datx.sellram(account,bytes,options,cb);
}


/**
 * 抵押获取CPU net
 * @param from 购买者
 * @param receiver 接收者
 * @param stake_net_quantity 用于购买带宽的token数量 '20 DATX'
 * @param stake_cpu_quantity 用于购买CPU的token数量 '20 DATX'
 * @param transfer  是否接受者可以主动解除抵押获得代币，如果不是，只有发起者能够解除抵押收回代币 (传数字0)
 * @param secret 私钥
 * @param cb 回调函数
 */
export function delegatebw(from,receiver,stake_net_quantity,stake_cpu_quantity,transfer,secret,cb) {
  userProvidedKey = secret;
  let options = {authorization: from + '@active'};
  datx.delegatebw(from,receiver,stake_net_quantity,stake_cpu_quantity,transfer,options,cb);
}



/**
 * 解除抵押获取CPU net
 * 需要等待72小时，再调用refund，资产才会回到账户中
 * @param from 解除用哪个账号所抵押的代币
 * @param receiver 解除作用在哪个账号上的抵押代币
 * @param unstake_net_quantity 解除用于购买带宽的token数量 '20 DATX'
 * @param unstake_cpu_quantity 解除用于购买带宽的token数量 '20 DATX'
 * @param secret 私钥
 * @param cb 回调函数
 */
export function undelegatebw(from,receiver,unstake_net_quantity,unstake_cpu_quantity,secret,cb) {
  userProvidedKey = secret;
  let options = {authorization: from + '@active'};
  datx.undelegatebw(from,receiver,unstake_net_quantity,unstake_cpu_quantity,options,cb);
}


/**
 * 解除抵押72小时后，领取资产
 * @param from 账户
 * @param secret 私钥
 * @param cb 回调函数
 */
export function refund(from,secret,cb){
  userProvidedKey = secret;
  let options = {authorization: from + '@active'};
  datx.refund(from,options,cb);
}


/**
 * 获取refund信息
 * @param account 账户
 * @param cb 回调函数
 */
export function getRefundInfo(account,cb){
  datx.getAccount(account).then(result =>{
    if(result.refund_request){
      let reqTime = Date.parse(result.refund_request.request_time + '+00:00')
      let now = Date.parse(Date());
      let rsec = (now - reqTime)/1000;
      return cb(null,{ cpu_amount:result.refund_request.cpu_amount,
                net_amount:result.refund_request.net_amount,
                seconds:rsec
              });
    }
    else{
      return cb(new error('invalid account'),null);
    }
  });
}



/**
 * 提币
 * @param from 提币账户
 * @param quant 提币资产与数量 '20.0000 DBTC'
 * @param memo 链外真实的提币地址
 * @param secret 私钥
 * @param cb 回调函数
 */
export function extract(from,quant,memo,secret,cb) {
  let type = quant.split(' ')[1];
  let to = "";
  switch(type){
    case "DBTC":
      to = "datxos.dbtc";
      break;
    case "DETH":
      to = "datxos.deth";
      break;
    case "DEOS":
      to = "datxos.deos";
  };

  datx.contract("datxos.dtoke").then(dtoke => { 
    userProvidedKey = secret;
    let options = {authorization: from + '@active'};
    dtoke.extract(from,to,quant,memo,options,cb);
  });
}



/**
 * 绑定地址
 * @param account DATX账户
 * @param address BTC或ETH地址
 * @param secret 私钥
 * @param cb 回调函数
 */
export function bindAddress(account,address,secret,cb) {
  datx.contract("datxos.charg").then(charge => { 
    userProvidedKey = secret;

    let options = {authorization: account + '@active'};
    charge.recorduser(account,address,options,cb);
  });
}


/**
 * 绑定地址
 * @param account DATX账户
 * @param prods producers节点列表 ['bp1','bp2'] 
 * @param secret 私钥
 * @param cb 回调函数
 */
export function vote(account,prods,secret,cb) {
  userProvidedKey = secret;

  let options = {authorization: account + '@active'};
  datx.voteproducer(account,proxy = '',prods,options,cb);
}
